package com.zhuxiaomei.service.impl;

import cn.hutool.core.util.ArrayUtil;
import com.zhuxiaomei.context.BaseContext;
import com.zhuxiaomei.dto.restaurant.*;
import com.zhuxiaomei.entity.restaurant.RestaurantCategory;
import com.zhuxiaomei.entity.restaurant.RestaurantDish;
import com.zhuxiaomei.entity.restaurant.RestaurantOrder;
import com.zhuxiaomei.entity.restaurant.RestaurantOrderDetail;
import com.zhuxiaomei.entity.user.Couple;
import com.zhuxiaomei.entity.user.User;
import com.zhuxiaomei.mapper.*;
import com.zhuxiaomei.service.RestaurantService;
import com.zhuxiaomei.utils.MinioUtils;
import com.zhuxiaomei.vo.restaurant.RestaurantCategoryVO;
import com.zhuxiaomei.vo.restaurant.RestaurantDishVO;
import com.zhuxiaomei.vo.restaurant.RestaurantOrderVO;
import jakarta.annotation.Resource;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hxm
 * @date 2024/11/10 15:44
 * @description
 */
@Service
public class RestaurantServiceImpl implements RestaurantService {


    @Resource
    private RestaurantCategoryMapper restaurantCategoryMapper;

    @Resource
    private RestaurantDishMapper restaurantDishMapper;

    @Resource
    private MinioUtils minioUtils;

    @Resource
    private RestaurantOrderMapper restaurantOrderMapper;

    @Resource
    private RestaurantOrderDetailMapper restaurantOrderDetailMapper;

    @Resource
    private CoupleMapper coupleMapper;

    @Resource
    private UserMapper userMapper;



    @Override
    public List<RestaurantCategoryVO> getCategoriesByStatus(String status) {

        List<RestaurantCategoryVO> restaurantCategoryVOList = new ArrayList<>();

        List<RestaurantCategory> restaurantCategoryList = restaurantCategoryMapper.selectCategoriesByStatus(status);

        if (ArrayUtil.isNotEmpty(restaurantCategoryList)) {
            for (RestaurantCategory item : restaurantCategoryList) {
                restaurantCategoryVOList.add(RestaurantCategoryVO.builder().id(item.getId()).categoryName(item.getCategoryName()).status(item.getStatus()).build());
            }
        }



        return restaurantCategoryVOList;
    }

    @Override
    public List<RestaurantDishVO> getRestaurantDishesByStatus(String status) {

        List<RestaurantDishVO> restaurantDishVOList = new ArrayList<>();
        //1.获取所有菜品信息
        List<RestaurantDish> restaurantDishList = restaurantDishMapper.selectDishByStatus(status);
        //2.为每个菜品创建图片URL，7天
        if (ArrayUtil.isNotEmpty(restaurantDishList)) {
            for (RestaurantDish item : restaurantDishList) {
                RestaurantDishVO restaurantDishVO = new RestaurantDishVO();
                BeanUtils.copyProperties(item, restaurantDishVO);
                String fileUrl = minioUtils.getFileUrl(restaurantDishVO.getDishImage());
                restaurantDishVO.setDishImage(fileUrl);
                restaurantDishVOList.add(restaurantDishVO);
            }
        }
        //3.返回数据

        return restaurantDishVOList;
    }

    @Override
    public Integer putChangeDishesStatus(List<RestaurantDishesStatusDTO> restaurantDishesStatusDTOList) {
        // 确保 status 是一个 Byte 类型的值
        Byte status = Byte.valueOf(restaurantDishesStatusDTOList.get(0).getStatus());

        // 将 ID 提取为 List<Long>（保持 Long 型）
        List<Long> idList = restaurantDishesStatusDTOList.stream()
                .map(RestaurantDishesStatusDTO::getId)  // 提取 id（假设该返回的是 Long）
                .collect(Collectors.toList());  // 收集到 List 中

        // 调用 Mapper 方法，传递 status 和 idList
        Integer row = restaurantDishMapper.updateStatusByBatchId(status, idList);

        return row;
    }

    @Override
    public List<RestaurantCategoryVO> getAllCategories() {
        List<RestaurantCategoryVO> allCategories = restaurantCategoryMapper.selectAllCategories();
        return allCategories;
    }


    @Override
    public Integer postAddDish(RestaurantDishDTO restaurantDishDTO) {
        RestaurantDish restaurantDish = new RestaurantDish();
        BeanUtils.copyProperties(restaurantDishDTO, restaurantDish);
        Integer row = restaurantDishMapper.insertRestaurantDish(restaurantDish);
        return row;
    }

    @Override
    public RestaurantDishVO getRestaurantDishById(Long id) {
        RestaurantDish restaurantDish =  restaurantDishMapper.selectOneById(id);
        RestaurantDishVO restaurantDishVO = new RestaurantDishVO();
        BeanUtils.copyProperties(restaurantDish, restaurantDishVO);
        String fileUrl = minioUtils.getFileUrl(restaurantDishVO.getDishImage());
        restaurantDishVO.setDishImage(fileUrl);
        return restaurantDishVO;
    }

    @Override
    public Integer putEditDish(RestaurantDishDTO restaurantDishDTO) {
        RestaurantDish restaurantDish = new RestaurantDish();
        BeanUtils.copyProperties(restaurantDishDTO, restaurantDish);
        int row = restaurantDishMapper.updateRestaurantDishById(restaurantDish);
        return row;
    }

    @Override
    public Integer deleteRestaurantDishById(Long id) {

        int row = restaurantDishMapper.deleteByPrimaryKey(id);

        return row;
    }

    @Override
    public Integer postAddCategory(RestaurantCategoryDTO restaurantCategoryDTO) {
        RestaurantCategory restaurantCategory = new RestaurantCategory();
        BeanUtils.copyProperties(restaurantCategoryDTO, restaurantCategory);
        Integer row = restaurantCategoryMapper.insertRestaurantCategory(restaurantCategory);
        return row;
    }

    @Override
    public Map<String, List<RestaurantDishVO>> getCategoryAndDishes(Byte status) {
        // 使用一个 HashMap 来存储结果
        Map<String, List<RestaurantDishVO>> categoryAndDishes = new HashMap<>();

        // 获取所有活动的餐厅类别
        List<RestaurantCategory> restaurantCategories = restaurantCategoryMapper.selectCategoriesByStatus(String.valueOf(status));

        // 遍历每个类别，构建对应的菜品信息
        for (RestaurantCategory category : restaurantCategories) {
            // 获取对应类别的菜品并转换为 VO 列表
            List<RestaurantDishVO> dishVOList = restaurantDishMapper
                    .selectRestaurantDishesByCategoryId(category.getId())
                    .stream()
                    .map(dish -> {
                        RestaurantDishVO restaurantDishVO = new RestaurantDishVO();
                        BeanUtils.copyProperties(dish, restaurantDishVO);
                        return restaurantDishVO;
                    })
                    .filter(dishVO -> dishVO.getDishName() != null) // 过滤掉特定 null 值的字段
                    .collect(Collectors.toList());

            // 将结果放入 Map
            categoryAndDishes.put(category.getCategoryName(), dishVOList);
        }

        return categoryAndDishes;
    }

    @Override
    public List<Long> getDishOnSaleByCategoryName(String categoryName) {
        //1.通过categoryName查询出categoryId
        Long categoryId = restaurantCategoryMapper.selectCategoryIdByCategoryName(categoryName);
        //2.根据categoryId查询出在售菜品的id

        List<Long> dishIds = restaurantDishMapper.selectDishOnsaleByCategoryId(categoryId);
        //3.返回
        return dishIds;
    }

    @Override
    public List<Long> getDishOnNoSaleByCategoryName(String categoryName) {
        //1.通过categoryName查询出categoryId
        Long categoryId = restaurantCategoryMapper.selectCategoryIdByCategoryName(categoryName);
        //2.根据categoryId查询出在售菜品的id

        List<Long> dishIds = restaurantDishMapper.selectDishOnNosaleByCategoryId(categoryId);
        //3.返回
        return dishIds;
    }

    @Override
    public Boolean changeCategoryAndDishesStatus(Byte status, List<RestaurantCategoryAndDishIdsDTO> restaurantCategoryAndDishIdsDTOList) {
        for (RestaurantCategoryAndDishIdsDTO restaurantCategoryAndDishIdsDTO : restaurantCategoryAndDishIdsDTOList) {
            List<Long> dishIds = restaurantCategoryAndDishIdsDTO.getDishIds();
            if (dishIds.size() > 0) {
                restaurantDishMapper.updateStatusByBatchId(status, dishIds);
            }
            restaurantCategoryMapper.updateStatusByCategoryName(status, restaurantCategoryAndDishIdsDTO.getCategoryName());
        }
        return true;
    }

    @Override
    public RestaurantCategoryVO getRestaurantCatetoryInfoByCategoryName(String categoryName) {
        RestaurantCategory restaurantCategory = restaurantCategoryMapper.selectCategoryByCategoryName(categoryName);
        RestaurantCategoryVO restaurantCategoryVO = new RestaurantCategoryVO();
        BeanUtils.copyProperties(restaurantCategory, restaurantCategoryVO);
        return restaurantCategoryVO;
    }

    @Override
    public Integer putRestaurantCategory(RestaurantCategoryDTO restaurantCategoryDTO) {
        RestaurantCategory restaurantCategory = new RestaurantCategory();
        BeanUtils.copyProperties(restaurantCategoryDTO, restaurantCategory);
        int row = restaurantCategoryMapper.updateByPrimaryKeySelective(restaurantCategory);
        return row;
    }

    @Override
    public Integer deleteCategoryByName(String categoryName) {
        Long categoryId = restaurantCategoryMapper.selectCategoryIdByCategoryName(categoryName);
        List<RestaurantDish> restaurantDishList = restaurantDishMapper.selectRestaurantDishesByCategoryId(categoryId);
        if (restaurantDishList.size() > 0) {
            // 使用 Streams API 提取 id 属性
            List<Long> idList = restaurantDishList.stream()
                    .map(RestaurantDish::getId) // 假设 getId() 返回 Long 类型
                    .collect(Collectors.toList());

            restaurantDishMapper.deleteByBathIds(idList);
        }
        Integer row = restaurantCategoryMapper.deleteByCategoryName(categoryName);
        return row;
    }

    @Override
    public String newOrder(List<RestaurantOrderDTO> restaurantOrderDTO) {
        // 使用流式计算来获取总价
        BigDecimal total = restaurantOrderDTO.stream()
                .map(order -> order.getPrice().multiply(new BigDecimal(order.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        User user = userMapper.selectByPrimaryKey(BaseContext.getCurrentId());
        if (user.getBalance().compareTo(total) < 0){
            return null;
        }
        //新增订单
        String orderNo = UUID.randomUUID().toString();
        RestaurantOrder restaurantNewOrder = RestaurantOrder.builder()
                .orderNo(orderNo)
                .status(1)
                .orderUserId(BaseContext.getCurrentId())
                .orderTime(LocalDateTime.now())
                .amount(total)
                .build();
        restaurantOrderMapper.insertNewOrder(restaurantNewOrder);
        //新增订单详情
        List<RestaurantOrderDetail> restaurantOrderDetailList  = new ArrayList<>();
        for (RestaurantOrderDTO item : restaurantOrderDTO){
            RestaurantOrderDetail orderDetail = new RestaurantOrderDetail();
            BeanUtils.copyProperties(item, orderDetail);
            String dishImage = item.getDishImage();
            String fileName = dishImage.substring(dishImage.lastIndexOf('/') + 1, dishImage.indexOf('?'));
            orderDetail.setDishImage(fileName);
            orderDetail.setOrderNo(orderNo);
            orderDetail.setDishId(item.getId());
            restaurantOrderDetailList.add(orderDetail);
        }
        restaurantOrderDetailMapper.insertOrderDetailBatch(restaurantOrderDetailList);
        return orderNo;
    }

    @Override
    public RestaurantOrderVO getRestaurantOrderInfoByOrderNo(String orderNo) {
        RestaurantOrder order = RestaurantOrder.builder().orderNo(orderNo).build();
        RestaurantOrderDetail orderDetail = RestaurantOrderDetail.builder().orderNo(orderNo).build();
        RestaurantOrder restaurantOrder = restaurantOrderMapper.selectOne(order);
        RestaurantOrderVO restaurantOrderVO = new RestaurantOrderVO();
        BeanUtils.copyProperties(restaurantOrder, restaurantOrderVO);
        List<RestaurantOrderDetail> orderDetails = restaurantOrderDetailMapper.select(orderDetail);
        orderDetails.forEach(item -> {
            item.setDishImage(minioUtils.getFileUrl(item.getDishImage()));
            item.setOrderNo(null);
        });
        restaurantOrderVO.setRestaurantOrderDetailList(orderDetails);
        return restaurantOrderVO;
    }

    @Override
    @Transactional
    public List<RestaurantOrderVO> getRestaurantOrderInfo(Integer status) {
        List<RestaurantOrderVO> restaurantOrderVOList = new ArrayList<>();
        //1.获取当前用户的情侣的id
        Long currentId = BaseContext.getCurrentId();
        Couple coupleInfo = coupleMapper.selectByManOrWomanID(currentId);
        //2.1根据status和当前用户的id获取相关订单
        RestaurantOrder manOrder = RestaurantOrder.builder().orderUserId(coupleInfo.getManId()).status(status).build();
        List<RestaurantOrder> manOrderList = restaurantOrderMapper.select(manOrder);
        for (RestaurantOrder restaurantOrder : manOrderList) {
            RestaurantOrderVO restaurantOrderVO = new RestaurantOrderVO();
            BeanUtils.copyProperties(restaurantOrder, restaurantOrderVO);
            RestaurantOrderDetail orderDetail = RestaurantOrderDetail.builder().orderNo(restaurantOrder.getOrderNo()).build();
            List<RestaurantOrderDetail> restaurantOrderDetailList = restaurantOrderDetailMapper.select(orderDetail);
            restaurantOrderDetailList.forEach(item -> {
                item.setDishImage(minioUtils.getFileUrl(item.getDishImage()));
                item.setOrderNo(null);
            });
            restaurantOrderVO.setRestaurantOrderDetailList(restaurantOrderDetailList);
            restaurantOrderVOList.add(restaurantOrderVO);
        }

        //3.1根据status和当前用户的情侣的id获取相关订单
        RestaurantOrder womanOrder = RestaurantOrder.builder().orderUserId(coupleInfo.getWomanId()).status(status).build();
        List<RestaurantOrder> womanOrderList = restaurantOrderMapper.select(womanOrder);
        for (RestaurantOrder restaurantOrder : womanOrderList) {
            RestaurantOrderVO restaurantOrderVO = new RestaurantOrderVO();
            BeanUtils.copyProperties(restaurantOrder, restaurantOrderVO);
            RestaurantOrderDetail orderDetail = RestaurantOrderDetail.builder().orderNo(restaurantOrder.getOrderNo()).build();
            List<RestaurantOrderDetail> restaurantOrderDetailList = restaurantOrderDetailMapper.select(orderDetail);
            restaurantOrderDetailList.forEach(item -> {
                item.setDishImage(minioUtils.getFileUrl(item.getDishImage()));
                item.setOrderNo(null);
            });
            restaurantOrderVO.setRestaurantOrderDetailList(restaurantOrderDetailList);
            restaurantOrderVOList.add(restaurantOrderVO);
        }
        //4.返回

        return restaurantOrderVOList;
    }

    @Override
    public void editRestaurantOrder(RestaurantOrderVO restaurantOrderVO) {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime formattedDateTime = LocalDateTime.parse(now.format(formatter), formatter);
        RestaurantOrder restaurantOrder = new RestaurantOrder();
        BeanUtils.copyProperties(restaurantOrderVO, restaurantOrder);
        if (restaurantOrder.getStatus() == 2) {
            restaurantOrder.setReceiveUserId(BaseContext.getCurrentId());
            restaurantOrder.setReceivedTime(formattedDateTime);
        } else if (restaurantOrder.getStatus() == 3) {
            //1.获取订单总金额
            RestaurantOrder order = restaurantOrderMapper.selectByOrderNo(restaurantOrder.getOrderNo());
            BigDecimal amount = order.getAmount();
            //2.获取下单用户的总金额
            User orderUser = userMapper.selectByPrimaryKey(order.getOrderUserId());

            //3.获取接单用户的总金额
            User receiveUser = userMapper.selectByPrimaryKey(order.getReceiveUserId());
            //4.更新用户表
            orderUser.setBalance(orderUser.getBalance().subtract(amount));
            userMapper.updateByPrimaryKeySelective(orderUser);

            receiveUser.setBalance(receiveUser.getBalance().add(amount));
            userMapper.updateByPrimaryKeySelective(receiveUser);
            restaurantOrder.setCheckoutTime(formattedDateTime);
        } else if (restaurantOrder.getStatus() == 4) {
            restaurantOrder.setCancelTime(formattedDateTime);
        }
        restaurantOrderMapper.updateByOrderNo(restaurantOrder);
    }
}
